import ApiError from "../error/ApiError";
import ApiErrorNames from "../error/ApiErrorNames";
import axios from "axios";
import shop from "../model/shop";
import DlyadminAiFuncsConfig from "../model/dlyadminAiFuncsConfig";
import JianceOrderModel from "../model/JianceOrderModel";
import redis from '../dbHelper/redis'
import mongoose from "mongoose";
import crypto from "crypto"
const AppKey = '202409261509475416'
const appSecret = 'ddf6748353855ddf03b53331d96509d0'

export class JianceApiController {
    static async batch(ctx) {
        console.log('ctx.request.body', ctx.request.body)
        if (!ctx.request.body) {
            throw new ApiError(ApiErrorNames.NoParamsData)
        }
        // const aiUser = JSON.parse(ctx.request.header.jwtuserinfo)
        const { jianceList, shop_id } = ctx.request.body

        //-----------参数校验开始--------
        if (!jianceList || !shop_id) {
            throw new ApiError(ApiErrorNames.selectInDengtData(`缺少参数`))
        }
        if (!Array.isArray(jianceList) || jianceList < 1) {
            throw new ApiError(ApiErrorNames.selectInDengtData(`缺少参数`))
        }

        for (const { ImgUrl, ItemId } of jianceList) {
            if (!ImgUrl || !ItemId) {
                throw new ApiError(ApiErrorNames.selectInDengtData(`参数异常`))
            }
        }

        const shopModel = await shop.findOne({
            shop_id: shop_id,
            // aiUserId: aiUser._id
        })

        if (!shopModel) {
            throw new ApiError(ApiErrorNames.selectInDengtData('店铺不存在'))
        }

        //-----------参数校验结束-------------

        //---------积分校验开始--------------
        let costConfig = await DlyadminAiFuncsConfig.findOne({ type: 'jiance', status: '1' })
        if (!costConfig) {
            throw new ApiError(ApiErrorNames.selectInDengtData('未设置当前接口收费模式'))
        }

        const costTotal = costConfig.num
        const batchId = new mongoose.Types.ObjectId()

        await this.lockScore(shopModel, costTotal * jianceList.length, async () => {
            const orderList = [];
            for (const { ImgUrl, ItemId, NeedCheckLogo = true } of jianceList) {
                const order = {
                    // owner_id: aiUser._id,
                    shop_id,
                    proxyId: shopModel.proxyId,
                    batchId,
                    status: 0,
                    api_request_data: {
                        ImgUrl,
                        ItemId: ItemId.toString(),
                        NeedCheckLogo: !!NeedCheckLogo,
                    },
                    costTotal,
                }
                const orderModel = await JianceOrderModel.create(order)

                orderModel.costTotal = costTotal

                await this.updateScore(orderModel)
                await orderModel.save()

                orderList.push(orderModel)
            }
            // return orderList
            //异步执行操作，不影响结果返回，暂时不想开启队列搞
            for (const orderModel of orderList) {

                if (orderModel.status !== 2) {//已支付待完成的订单才需要进行操作
                    continue
                }
                //失败后退款
                const orderFail = async (msg) => {
                    console.log('检测接口失败', orderModel, msg)
                    await shop.updateOne({
                        shop_id: orderModel.shop_id,
                    }, {
                        $inc: {
                            jianceScore: orderModel.costScore || 0,
                            jianceSendScore: orderModel.costSendScore || 0,
                        }
                    })

                    orderModel.status = -2
                    orderModel.errorMessage = msg
                    await orderModel.save()
                }

                //请求接口，等待接口响应
                this.apiRequest(orderModel).then(({ data }) => {
                    if (data.code !== 0) {
                        orderFail('结果出错：' + JSON.stringify(data))
                        return null
                    }
                    orderModel.api_response_data = data.result
                    orderModel.status = 1
                    orderModel.save()
                    return null
                }).catch((err) => {
                    orderFail('连接错误：' + err.message)
                })
            }
        })

        ctx.body = {
            batchId: batchId.toString()
        }
    }

    static async batchResult(ctx) {
        if (!ctx.request.body) {
            throw new ApiError(ApiErrorNames.NoParamsData)
        }

        if (!ctx.request.body) {
            throw new ApiError(ApiErrorNames.NoParamsData)
        }
        const { batchId, shop_id } = ctx.request.body
        if (!batchId || !shop_id) {
            throw new ApiError(ApiErrorNames.selectInDengtData(`缺少参数`))
        }

        const orderList = await JianceOrderModel.find({
            batchId,
            shop_id,
        })
        console.log('orderList', orderList)
        ctx.body = {
            total: orderList.length,
            successNum: orderList.filter(orderModel => {//成功数量
                return orderModel.status === 1
            }).length,
            failNum: orderList.filter(orderModel => {//失败数量
                return orderModel.status < 0
            }).length,
            list: orderList.map(orderModel => {
                return {
                    status: orderModel.status,
                    req: orderModel.api_request_data,
                    result: orderModel.api_response_data || null,
                }
            })
        }
    }


    static async create(ctx) {
        console.log('ctx.request.body', ctx.request.body)
        if (!ctx.request.body) {
            throw new ApiError(ApiErrorNames.NoParamsData)
        }
        // const aiUser = JSON.parse(ctx.request.header.jwtuserinfo)
        const { ImgUrl, ItemId, NeedCheckLogo = true, shop_id } = ctx.request.body

        //-----------参数校验开始--------
        if (!ImgUrl || !ItemId || !shop_id) {
            throw new ApiError(ApiErrorNames.selectInDengtData(`缺少参数`))
        }

        const shopModel = await shop.findOne({
            shop_id: shop_id,
            // aiUserId: aiUser._id
        })

        if (!shopModel) {
            throw new ApiError(ApiErrorNames.selectInDengtData('店铺不存在'))
        }

        //-----------参数校验结束-------------

        //---------积分校验开始--------------
        let costConfig = await DlyadminAiFuncsConfig.findOne({ type: 'jiance', status: '1' })
        if (!costConfig) {
            throw new ApiError(ApiErrorNames.selectInDengtData('未设置当前接口收费模式'))
        }

        const costTotal = costConfig.num

        //锁定库存
        const orderModel = await this.lockScore(shopModel, costTotal, async () => {
            const order = {
                // owner_id: aiUser._id,
                shop_id,
                proxyId: shopModel.proxyId,
                status: 0,
                api_request_data: {
                    ImgUrl,
                    ItemId: ItemId.toString(),
                    NeedCheckLogo: !!NeedCheckLogo,
                },
            }

            const orderModel = await JianceOrderModel.create(order)
            const orderFail = async (msg) => {
                console.log('检测接口失败', orderModel._id, msg)
                orderModel.status = -3
                orderModel.errorMessage = msg
                await orderModel.save()
                throw new ApiError(ApiErrorNames.selectInDengtData(msg))
            }

            //请求接口，等待接口响应
            const { data } = await this.apiRequest(orderModel).catch(async (err) => {
                await orderFail('连接错误：' + err.message)
            })

            if (data.code !== 0) {
                await orderFail('结果出错：' + JSON.stringify(data))
            }

            orderModel.api_response_data = data.result
            orderModel.costTotal = costTotal

            //扣除积分
            await this.updateScore(orderModel)

            await orderModel.save()
            return orderModel;
        })

        return ctx.body = {
            result: orderModel.api_response_data,
        }
    }

    static async apiRequest(orderModel) {
        const Method = 'against.searchAgainstSameGoods'
        const Timestamp = Math.floor(Date.now() / 1000)

        const md5 = crypto.createHash('md5');
        const Sign = md5.update([
            appSecret,
            AppKey,
            Method,
            Timestamp,
            appSecret
        ].join('')).digest('hex')

        return await axios.post('http://fy.b5.zzbtool.com/open/router', {
            AppKey,
            Method,
            Timestamp,
            ParamJson: JSON.stringify({
                ...orderModel.api_request_data,
                Uid: orderModel.shop_id + '',
            }),
            Sign
        }, { timeout: 30 * 1000 })
    }

    static async lockScore(shopModel, costTotal, callback) {
        const lockKey = `shopLockScore${shopModel.shop_id}`
        const lockScore = parseInt(await redis.get(lockKey) || 0)
        if (lockScore < 0) {
            //排除数据异常情况，希望用不上
            console.log('锁定店铺积分异常：', lockScore)
            await redis.del(lockKey)
        }

        //检测并锁定积分
        if ((shopModel.jianceScore || 0) + (shopModel.jianceSendScore || 0) < lockScore + costTotal) {
            throw new ApiError(ApiErrorNames.selectInDengtData('店铺积分不足'))
        }
        //---------积分校验结束--------------

        //锁定积分，有效期35秒
        await redis.incrby(lockKey, costTotal)
        await redis.expire(lockKey, 35)

        try {
            return await callback()
        } finally {
            //无论出错还是成功，释放锁定积分
            if (await redis.get(lockKey)) {//先查询在释放，避免出现超时导致重复多释放的问题
                await redis.decrby(lockKey, costTotal)
            }
        }
    }

    static async updateScore(orderModel) {
        //获取最新数据
        const shopModel = await shop.findOne({
            shop_id: orderModel.shop_id,
            // aiUserId: orderModel.owner_id
        })

        //未找到店铺的情况，基本不应该出现
        if (!shopModel) {
            orderModel.costTotal = 0
            orderModel.status = -1
            return;
        }

        if (shopModel.jianceScore < orderModel.costTotal) {//积分不足的情况先扣积分，再扣赠送积分
            // console.log('不够0022扣', shopModel)
            orderModel.costScore = shopModel.jianceScore;
            shopModel.jianceScore = 0;
            orderModel.costSendScore = (orderModel.costTotal || 0) - (orderModel.costScore || 0)
            shopModel.jianceSendScore -= (orderModel.costSendScore || 0)
        } else {
            orderModel.costScore = orderModel.costTotal || 0
            orderModel.costSendScore = 0
            shopModel.jianceScore -= orderModel.costScore || 0
        }
        await shopModel.save()

        //如果已经有结果，那表示订单已完成
        orderModel.status = orderModel.api_response_data ? 1 : 2
        return orderModel;
    }

    static async history(ctx) {
        console.log('检测历史记录', ctx.query)
        const { pageSize = 10, page = 1, ItemId = null, cheackStatus } = ctx.query
        let addShearData = { shop_id: ctx.query.shop_id * 1, status: 1 }
        if (ItemId) {
            addShearData['api_request_data.ItemId'] = ItemId
        }
        if (cheackStatus) {
            if (cheackStatus == 0) {
                addShearData['api_response_data.Status'] = 0
                // addShearData['api_response_data.CheckLogoStatus'] = 0
            }
            if (cheackStatus == 1) {
                addShearData['api_response_data.Status'] = 1
                // addShearData['api_response_data.CheckLogoStatus'] = 1
            }
        }
        const getList = await JianceOrderModel.find(addShearData)
            // .where('api_request_data.ItemId')
            // .equals('3709788346474692815')
            .sort({ createTime: -1 })
            .limit(pageSize * 1)
            .skip((page - 1) * pageSize)
        // console.log('getListgetList', getList)
        return ctx.body = {
            list: getList,
            total: await JianceOrderModel.find(addShearData).countDocuments()
        }
    }

}


